from exts import db
from common import constant
from app.order.model_mixin import OrderModelMixin
from common.base_model import BasicModelMixin, CompanyMixin, CreateMixin, UpdateMixin, DeleteMixin
from common import errors
from app.storage.storage_record.model import StorageRecord
from app.storage.storage_flow.model import StorageFlow
from common.constant import OrderStatus, OrderType
from app.finance.account_flow.model import AccountFlow


class SaleOrder(BasicModelMixin, db.Model, OrderModelMixin, CompanyMixin, CreateMixin, UpdateMixin, DeleteMixin):
    __tablename__ = 'sale_order'

    tracking_number = db.Column(db.String(constant.LONG_DB_STR_LEN))  # 快递单号
    is_make = db.Column(db.Boolean, default=False, server_default="False")  # 是否已开票
    bill_info = db.Column(db.String(constant.LONG_DB_STR_LEN))  # 开票信息
    income = db.Column(db.DECIMAL(20, constant.COMMON_DECIMAL), default=0)  # 实收金额
    reduce_price = db.Column(db.DECIMAL(20, constant.COMMON_DECIMAL), default=0)  # 抹零金额

    account_id = db.Column(db.Integer, db.ForeignKey('account.id'))  # 结算账户

    customer_id = db.Column(db.Integer, db.ForeignKey('customer.id'))
    warehouse_id = db.Column(db.Integer, db.ForeignKey('warehouse.id'))

    customer = db.relationship('Customer')
    warehouse = db.relationship("Warehouse")
    account = db.relationship("Account", foreign_keys='SaleOrder.account_id')

    order_skus = db.relationship("SaleOrderSku", back_populates='sale_order',
                                 cascade="all, delete, delete-orphan")

    def save_draft(self, order_skus_json, image_ids, **kwargs):
        self.check_draft_status()
        # 更新order
        self.update(**kwargs)
        # 更新 order_sku
        for order_sku in self.order_skus:
            order_sku.hard_delete()  # 先删
        for order_sku_json in order_skus_json:
            SaleOrderSku.create(order_id=self.id, **order_sku_json)  # 后增

        # 更新images
        self.update_images(image_ids)
        db.session.commit()

    def update_images(self, image_ids):
        self.update_images_by_belong_type(image_ids, constant.FileBelongType.SALE_ORDER)

    def submit(self):
        """入库，入账"""
        self.status = OrderStatus.SUCCESS  # 修改order状态
        self.update_warehouse_record()  # 更新库存
        self.create_warehouse_flow()  # 创建库存流水
        self.create_account_flow()  # 创建财务流水
        db.session.commit()

    def revoke(self):
        """回退入库，回退财务"""
        if self.status != OrderStatus.SUCCESS:
            raise errors.BadRequestError('无法撤销，只有已完成单据可撤销！')
        self.status = OrderStatus.REVOKE  # 修改order状态
        self.revoke_warehouse_record()  # 回退库存
        self.delete_warehouse_flow()  # 删除库存流水
        self.delete_account_flow()  # 删除财务流水
        db.session.commit()

    def update_warehouse_record(self):
        """销售出库 减少数量, 修改成本单价"""
        for order_sku in self.order_skus:
            """"""
            # get or create
            storage_record = StorageRecord.query.filter_by(
                warehouse_id=self.warehouse_id, sku_id=order_sku.sku_id, unit_id=order_sku.unit_id
            ).first()
            if storage_record is None:
                # todo, 会出现负库存
                storage_record = StorageRecord.create(
                    warehouse_id=self.warehouse_id, sku_id=order_sku.sku_id, unit_id=order_sku.unit_id,
                    commit=True
                )
            # 减少库存数量
            storage_record.num -= order_sku.num
            # 修改成本单价（销售不修改库存成功单价）
            # storage_record.update_cost_price(-order_sku.num, order_sku.discount_price)

    def revoke_warehouse_record(self):
        """销售撤销 增加数量, 修改成本单价"""
        for order_sku in self.order_skus:
            storage_record = StorageRecord.query.filter_by(
                warehouse_id=self.warehouse_id, sku_id=order_sku.sku_id, unit_id=order_sku.unit_id
            ).first()
            storage_record.num += order_sku.num
            # 修改成本单价 （销售不修改库存成功单价）
            # storage_record.update_cost_price(order_sku.num, order_sku.discount_price)

    def create_warehouse_flow(self):
        for order_sku in self.order_skus:
            StorageFlow.create(
                warehouse_id=self.warehouse_id, sku_id=order_sku.sku_id, unit_id=order_sku.unit_id,
                order_type=OrderType.SALE, order_id=self.id, num=-order_sku.num,
            )

    def delete_warehouse_flow(self):
        for order_sku in self.order_skus:
            StorageFlow.query.filter_by(
                warehouse_id=self.warehouse_id, sku_id=order_sku.sku_id, unit_id=order_sku.unit_id,
                order_type=OrderType.SALE, order_id=self.id,
            ).first().hard_delete()

    def create_account_flow(self):
        # 创建财务流水
        AccountFlow.create(
            transaction_type=constant.TransactionType.SALE,
            account_id=self.account_id,
            customer_id=self.customer_id,
            order_id=self.id,
            should_income=self.total_should_income,
            income=self.income
        )

    def delete_account_flow(self):
        # 删除财务流水
        AccountFlow.query.filter_by(
            account_id=self.account_id,
            transaction_type=constant.TransactionType.SALE,
            order_id=self.id,
        ).first().hard_delete()

    @property
    def total_should_income(self):
        should_income = 0
        for order_sku in self.order_skus:
            should_income += order_sku.total_discount_price
        # 抹零金额
        should_income = should_income - self.reduce_price
        return should_income

    @classmethod
    def generate_order_sn_sale(cls, prefix='XS'):
        return cls.generate_order_sn(prefix)


class SaleOrderSku(BasicModelMixin, db.Model, CompanyMixin, CreateMixin, DeleteMixin):
    __tablename__ = 'sale_order_sku'

    id = db.Column(db.Integer, primary_key=True)
    order_id = db.Column(db.Integer, db.ForeignKey('sale_order.id'))
    sale_order = db.relationship("SaleOrder", foreign_keys="SaleOrderSku.order_id")

    sku_id = db.Column(db.Integer, db.ForeignKey('sku.id'))
    unit_id = db.Column(db.Integer, db.ForeignKey('unit.id'))

    num = db.Column(db.DECIMAL(20, constant.COMMON_DECIMAL), default=0)  # 数量
    price = db.Column(db.DECIMAL(20, constant.COMMON_DECIMAL), default=0)  # 单价
    discount = db.Column(db.DECIMAL(20, constant.COMMON_DECIMAL), default=1, server_default='1')  # 折扣
    sku = db.relationship("Sku")
    unit = db.relationship("Unit")

    @property
    def total_discount_price(self):
        return self.price * self.num * self.discount

    @property
    def discount_price(self):
        return self.price * self.discount
